﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;

namespace Agile.DataAccess
{
    internal class SelectBuilder<TEntity> : BaseSelectBuilder,ISelectBuilder<TEntity>
    {
        public SelectBuilder(IDbCommand command, string name)
            :base(command, name){ }
        private IDbCommand GetPreparedDbCommand()
        {
            if (Data.PagingItemsPerPage > 0 && Data.OrderBy.Count == 0)
                throw new FluentDataException("Order by must defined when using Paging.");

            Data.Command.ClearSql.Script(Data.Command.Data.Context.Data.FluentDataProvider.GetSqlForSelectBuilder(Data, true));
            return Data.Command;
        }

        internal virtual ISelectBuilder<TEntity> AutoMap(params Expression<Func<TEntity, object>>[] ignoreProperties)
        {
            TEntity item = System.Activator.CreateInstance<TEntity>();
            Data.Item = item;
            //Data.ObjectName = typeof(TEntity).Name;
            Actions.AutoMapFieldAction(ignoreProperties);
            return this;
        }

        public virtual ISelectBuilder<TEntity> Where(string columnName, object value, DataTypes parameterType, int size)
        {
            Actions.WhereAction(columnName, value, parameterType, size);
            return this;
        }

        public virtual ISelectBuilder<TEntity> OrderBy(string columnName, string value, DataTypes parameterType, int size)
        {
            string sort = value.ToLower().Trim().Equals("asc") == false && value.ToLower().Trim().Equals("desc") == false ? "ASC" : value.Trim().ToUpper();
            Actions.OrderByAction(columnName, sort, parameterType, size);
            return this;
        }

        public ISelectBuilder<TEntity> Paging(int currentPage, int itemsPerPage)
        {
            Data.PagingCurrentPage = currentPage;
            Data.PagingItemsPerPage = itemsPerPage;
            return this;
        }

        public List<TEntity> QueryMany(Action<TEntity, IDataReader> customMapper = null)
        {
            this.AutoMap();
            return GetPreparedDbCommand().QueryMany<TEntity>(customMapper);
        }

        public List<TEntity> QueryMany(Action<TEntity, dynamic> customMapper)
        {
            this.AutoMap();
            return GetPreparedDbCommand().QueryMany<TEntity>(customMapper);
        }

        public TList QueryMany<TList>(Action<TEntity, IDataReader> customMapper = null) where TList : IList<TEntity>
        {
            this.AutoMap();
            return GetPreparedDbCommand().QueryMany<TEntity, TList>(customMapper);
        }

        public TList QueryMany<TList>(Action<TEntity, dynamic> customMapper) where TList : IList<TEntity>
        {
            this.AutoMap();
            return GetPreparedDbCommand().QueryMany<TEntity, TList>(customMapper);
        }

        public void QueryComplexMany(IList<TEntity> list, Action<IList<TEntity>, IDataReader> customMapper)
        {
            this.AutoMap();
            GetPreparedDbCommand().QueryComplexMany<TEntity>(list, customMapper);
        }

        public void QueryComplexMany(IList<TEntity> list, Action<IList<TEntity>, dynamic> customMapper)
        {
            this.AutoMap();
            GetPreparedDbCommand().QueryComplexMany<TEntity>(list, customMapper);
        }

        public TEntity QuerySingle(Action<TEntity, IDataReader> customMapper = null)
        {
            this.AutoMap();
            return GetPreparedDbCommand().QuerySingle<TEntity>(customMapper);
        }

        public TEntity QuerySingle(Action<TEntity, dynamic> customMapper)
        {
            this.AutoMap();
            return GetPreparedDbCommand().QuerySingle<TEntity>(customMapper);
        }

        public TEntity QueryComplexSingle(Func<IDataReader, TEntity> customMapper)
        {
            this.AutoMap();
            return GetPreparedDbCommand().QueryComplexSingle(customMapper);
        }

        public TEntity QueryComplexSingle(Func<dynamic, TEntity> customMapper)
        {
            this.AutoMap();
            return GetPreparedDbCommand().QueryComplexSingle(customMapper);
        }
    }
}
